﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

using System.Net;
using SharpSvn;

namespace Might.ServiceServer.SvnAccess {

    /// <summary>
    /// Class securing communication with subversion.
    /// </summary>
    public static class Svn {

        /// <summary>
        /// Performs a recursive checkout from address_from to address_where. 
        /// </summary>
        /// <param name="address_from">Repository address.</param>
        /// <param name="address_where">Destination address.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns>True if checkout is successfully completed, False otherwise.</returns>
        public static bool Checkout(string address_from, string address_where, string username, string password) {
            SvnClient client = new SvnClient();
            SvnUriTarget target;
            if (string.IsNullOrEmpty(address_from) || !SvnUriTarget.TryParse(address_from, out target)) {
                return false;
            }
            else {
                if (string.IsNullOrEmpty(username)) {
                    return client.CheckOut(target, address_where);
                }
                else {
                    client.Authentication.DefaultCredentials = new NetworkCredential(username, password);
                    return client.CheckOut(target, address_where);
                }
            }
        }

        /// <summary>
        /// Save changes from your working copy to the repository.
        /// </summary>
        /// <param name="from_where">Addrees from where will be changes saved.</param>
        /// <returns>True if commit is successfully completed, False otherwise.</returns>
        public static bool Commit(string from_where) {
            SvnClient client = new SvnClient();
            return client.Commit(from_where);
        }

        /// <summary>
        /// Gets Information (revision number) about the spocific repository.
        /// </summary>
        /// <param name="address_from">Repository address.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns></returns>
        public static string Info(string address_from, string username, string password) {
            SvnClient client = new SvnClient();
            SvnInfoEventArgs info;
            SvnUriTarget target;
            if (string.IsNullOrEmpty(address_from) || !SvnUriTarget.TryParse(address_from, out target)) {
                return "";
            }
            else {
                if (string.IsNullOrEmpty(username)) {
                    client.GetInfo(target, out info);
                    return info.Revision.ToString();
                }
                else {
                    client.Authentication.DefaultCredentials = new NetworkCredential(username, password);
                    client.GetInfo(target, out info);
                    return info.Revision.ToString();
                }
            }
        }
        
        /// <summary>
        /// Returns list of files in repository. (svn list)
        /// </summary>
        /// <param name="address_from">Repository address.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns>List of files in repository on current address.</returns>
        public static List<string> List(string address_from, string username, string password) {
            SvnClient client = new SvnClient();
            Collection<SvnListEventArgs> list;
            SvnUriTarget target;
            List<string> svnList = new List<string>();
            if (string.IsNullOrEmpty(address_from) || !SvnUriTarget.TryParse(address_from, out target)) {
                return svnList;
            }
            else {
                if (string.IsNullOrEmpty(username)) {
                    client.GetList(target, out list);
                }
                else {
                    client.Authentication.DefaultCredentials = new NetworkCredential(username, password);
                    client.GetList(target, out list);
                }

                foreach (SvnListEventArgs item in list) {
                    if (item.Path != "") {
                        SvnInfoEventArgs baf;
                        client.GetInfo(item.BaseUri + item.Path, out baf);
                        if (baf.Uri.ToString().EndsWith("/")){
                            svnList.Add(item.Path + "/");
                        }
                        else {
                            svnList.Add(item.Path);
                        }
                        //svnList.Add(item.Path + " " + item.BasePath + " " + item.BaseUri + " " + baf.Uri);
                    }
                }
                
                return svnList;
            }
        }

        /// <summary>
        /// Add file or directory to the reepository.
        /// </summary>
        /// <param name="address_from">Repository address.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns>True if commit is successfully completed, False otherwise.</returns>
        public static bool Add(string address, string username, string password) {

            SvnClient client = new SvnClient();
            bool Result;
            
            if (! string.IsNullOrEmpty(username)) {
                client.Authentication.DefaultCredentials = new NetworkCredential(username, password);
            }

            try {
                client.Add(address);
                Result = true;
            }
            catch {
                Result = false;
            }

            return Result;

        }

    }

}
